package com.googlecode.fxutils;

/*
Copyright (c) 2014, Carlos Eduardo Klock.
All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.

3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific
prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

import com.googlecode.fxutils.FxUtils.SameSize;
import java.util.List;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Orientation;
import javafx.geometry.Pos;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.text.Text;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.Window;
import javafx.stage.WindowEvent;

/**
 * Utilities to display dialog windows.
 * This class can be initialized as a Singleton or a normal instance.
 *
 * @author Carlos Eduardo Klock   07/04/2014
 */
public class DialogUtils {

    private DialogUtils() {
    }

    /**
     * Creates a dialog with no content.
     * The dialog is centralized on the owner by default.
     * @param owner      the owner of the dialog.
     * @param modality   the modality of the dialog.
     * @return the created dialog.
     */
    public static Stage createDialog(final Window owner, final Modality modality) {
        DialogProperties properties = DialogProperties.builder(owner).modality(modality).build();
        return createDialog(properties, null);
    }

    /**
     * Creates a dialog.
     * The dialog is centralized on the owner by default.
     * @param owner      the owner of the dialog.
     * @param content    the scene content of the dialog.
     * @param modality   the modality of the dialog.
     * @return the created dialog.
     */
    public static Stage createDialog(final Window owner, final Scene content, final Modality modality) {
        DialogProperties properties = DialogProperties.builder(owner).modality(modality).build();
        return createDialog(properties, content);
    }

    /**
     * Creates a dialog.
     * @param p  the properties of the dialog.
     * @return the created dialog.
     */
    public static Stage createDialog(final DialogProperties p) {
        return createDialog(p, null);
    }

    /**
     * Creates a dialog.
     * @param p        the properties of the dialog.
     * @param content  the scene content of the dialog.
     * @return the created dialog.
     */
    public static Stage createDialog(final DialogProperties p, final Scene content) {
        final Stage dialog = new Stage(p.getDecoration());
        dialog.initOwner(p.getOwnerWindow());
        dialog.initModality(p.getModality());
        dialog.setTitle(p.getTitle());

        if (content != null) {
            content.getRoot().setStyle(p.getCss());
            dialog.setScene(content);
            dialog.setResizable(false);
            dialog.sizeToScene();
        }

        if (p.isCentralizeOnOwner()) {
            dialog.setOnShown(new EventHandler<WindowEvent>() {
                @Override
                public void handle(WindowEvent e) {
                    FxUtils.centralizeOnOwner(dialog, p.getOwnerWindow());
                }
            });
        }

        return dialog;
    }

    /**
     * Shows an option dialog.
     * @param p        the properties of the dialog.
     * @param content  the content of the dialog.
     * @param buttons  array containing the text of the buttons that will be diplayed in the dialog.
     * @return the text of the button that was clicked. Null if the dialog was closed.
     */
    public static String showOptionDialog(final DialogProperties p, final Parent content, final String... buttons) {
        final VBox vbox = new VBox(10);
        final List<Button> buttonList = FxUtils.createButtons(buttons);
        final String[] clickedButton = new String[1];
        final Stage dialog;

        // CONTENT.
        vbox.getChildren().add(content);
        // BUTTONS.
        vbox.getChildren().add(FxUtils.createButtonPane(Orientation.HORIZONTAL, buttonList, Pos.CENTER, 10, SameSize.WIDTH));
        vbox.setPadding(p.getPadding());

        // DIALOG.
        dialog = createDialog(p, new Scene(vbox));
        dialog.setTitle(p.getTitle());

        // LISTENER.
        EventHandler<ActionEvent> buttonHandler = new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent e) {
                clickedButton[0] = ((Button)e.getSource()).getText();
                dialog.hide();
            }
        };
        for (Button button : buttonList) {
            button.setOnAction(buttonHandler);
        }

        dialog.showAndWait();

        return clickedButton[0];
    }

    /**
     * Shows an option dialog.
     * @param owner    the owner of the dialog.
     * @param content  the content of the dialog.
     * @param buttons  array containing the text of the buttons that will be diplayed in the dialog.
     * @return the text of the button that was clicked. Null if the dialog was closed.
     */
    public static String showOptionDialog(final Window owner, final Parent content, final String... buttons) {
        return showOptionDialog(DialogProperties.getDefault(owner), content, buttons);
    }

    /**
     * Shows an option dialog.
     * @param p         the properties of the dialog.
     * @param message   the message of the dialog.
     * @param buttons   array containing the text of the buttons that will be diplayed in the dialog.
     * @return the text of the button that was clicked. Null if the dialog was closed.
     */
    public static String showOptionDialog(final DialogProperties p, final String message, final String... buttons) {
        Text text = new Text(message);
        text.setFont(p.getFont());
        HBox hbox = new HBox();
        hbox.setAlignment(Pos.CENTER);
        hbox.getChildren().add(text);
        return showOptionDialog(p, hbox, buttons);
    }

    /**
     * Shows an option dialog.
     * @param owner     the owner of the dialog.
     * @param message   the message of the dialog.
     * @param buttons   array containing the text of the buttons that will be diplayed in the dialog.
     * @return the text of the button that was clicked. Null if the dialog was closed.
     */
    public static String showOptionDialog(final Window owner, final String message, final String... buttons) {
        return showOptionDialog(DialogProperties.getDefault(owner), message, buttons);
    }

    /**
     * Shows a message dialog with "OK" button.
     * @param owner     the owner of the dialog.
     * @param message   the message of the dialog.
     * @return "OK" if the button was clicked. Null if the dialog was closed.
     */
    public static String showMsgDialog(final Window owner, final String message) {
        return showOptionDialog(DialogProperties.getDefault(owner), message, "OK");
    }

    /**
     * Shows a message dialog with "OK" button.
     * @param p         the properties of the dialog.
     * @param message   the message of the dialog.
     * @return "OK" if the button was clicked. Null if the dialog was closed.
     */
    public static String showMsgDialog(final DialogProperties p, final String message) {
        return showOptionDialog(p, message, "OK");
    }

}
